home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume21 / amd / part09 < prev    next >
Encoding:
Internet Message Format  |  1990-04-10  |  51.4 KB

  1. Subject:  v21i097:  An Automounter for NFS systems, Part09/13
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: fe22683e d1a900ce d6c31acc fc4a3c8d
  5.  
  6. Submitted-by: Jan-Simon Pendry <jsp@doc.ic.ac.uk>
  7. Posting-number: Volume 21, Issue 97
  8. Archive-name: amd/part09
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 9 (of 13)."
  17. # Contents:  am.h nfs_ops.c util.c
  18. # Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:13 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'am.h' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'am.h'\"
  22. else
  23. echo shar: Extracting \"'am.h'\" \(17876 characters\)
  24. sed "s/^X//" >'am.h' <<'END_OF_FILE'
  25. X/*
  26. X * $Id: am.h,v 5.1.1.2 90/01/11 16:59:18 jsp Exp Locker: jsp $
  27. X *
  28. X * Copyright (c) 1990 Jan-Simon Pendry
  29. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  30. X * Copyright (c) 1990 The Regents of the University of California.
  31. X * All rights reserved.
  32. X *
  33. X * This code is derived from software contributed to Berkeley by
  34. X * Jan-Simon Pendry at Imperial College, London.
  35. X *
  36. X * Redistribution and use in source and binary forms are permitted
  37. X * provided that the above copyright notice and this paragraph are
  38. X * duplicated in all such forms and that any documentation,
  39. X * advertising materials, and other materials related to such
  40. X * distribution and use acknowledge that the software was developed
  41. X * by Imperial College of Science, Technology and Medicine, London, UK.
  42. X * The names of the College and University may not be used to endorse
  43. X * or promote products derived from this software without specific
  44. X * prior written permission.
  45. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  46. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  47. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  48. X *
  49. X *    %W% (Berkeley) %G%
  50. X */
  51. X
  52. X/*
  53. X * Get this in now so that OS_HDR can use it
  54. X */
  55. X#ifdef __STDC__
  56. X#define    P(x) x
  57. X#define    P_void void
  58. X#else
  59. X#define P(x) ()
  60. X#define P_void /* as nothing */
  61. X#define const /* as nothing */
  62. X#endif
  63. X
  64. X#ifdef __GNUC__
  65. X#define INLINE /* __inline */
  66. X#else
  67. X#define    INLINE
  68. X#endif
  69. X
  70. X/*
  71. X * Pick up target dependent definitions
  72. X */
  73. X#include "os-defaults.h"
  74. X#include OS_HDR
  75. X
  76. X#ifdef VOIDP
  77. Xtypedef void *voidp;
  78. X#else
  79. Xtypedef char *voidp;
  80. X#endif
  81. X
  82. X/*
  83. X * Global declarations
  84. X */
  85. X#include <stdio.h>
  86. X#include <sys/param.h>
  87. X#include <sys/errno.h>
  88. Xextern int errno;
  89. X#include <sys/socket.h>
  90. X#include <rpc/rpc.h>
  91. X#include "nfs_prot.h"
  92. X#ifdef MNTENT_HDR
  93. X#include MNTENT_HDR
  94. X#endif
  95. X#include <sys/time.h>
  96. X#include <assert.h>
  97. X
  98. X#ifdef DEBUG_MEM
  99. X#include <malloc.h>
  100. X#endif
  101. X
  102. X#ifndef MAXHOSTNAMELEN
  103. X#define MAXHOSTNAMELEN 64
  104. X#endif
  105. X
  106. X#ifndef MNTTYPE_AUTO
  107. X#define MNTTYPE_AUTO "auto"
  108. X#endif
  109. X
  110. X#ifndef FALSE
  111. X#define FALSE 0
  112. X#define TRUE 1
  113. X#endif
  114. X
  115. X#ifndef ROOT_MAP
  116. X#define    ROOT_MAP "\"root\""
  117. X#endif
  118. X
  119. X/*
  120. X * Flags from command line
  121. X */
  122. Xextern int print_pid;        /* Print pid to stdout */
  123. Xextern int normalize_hosts;    /* Normalize host names before use */
  124. Xextern int restart_existing_mounts;
  125. X#ifdef HAS_YP_MAPS
  126. Xextern char *domain;        /* YP domain to use */
  127. X#endif
  128. Xextern FILE *logfp;        /* Log file */
  129. Xextern int xlog_level;        /* Logging level */
  130. X#ifdef HAS_SYSLOG
  131. Xextern int syslogging;        /* Really using syslog */
  132. X#endif
  133. Xextern int am_timeo;        /* Cache period */
  134. Xextern int afs_timeo;        /* AFS timeout */
  135. Xextern int afs_retrans;        /* AFS retrans */
  136. Xextern int am_timeo_w;        /* Unmount timeout */
  137. Xextern char *mtab;        /* Mount table */
  138. X
  139. X#define    XLOG_FATAL    0x0001
  140. X#define    XLOG_ERROR    0x0002
  141. X#define    XLOG_USER    0x0004
  142. X#define    XLOG_WARNING    0x0008
  143. X#define    XLOG_INFO    0x0010
  144. X#define    XLOG_DEBUG    0x0020
  145. X#define    XLOG_MAP    0x0040
  146. X#define    XLOG_STATS    0x0080
  147. X
  148. X#define XLOG_DEFSTR    "all,nomap,nostats"        /* Default log options */
  149. X#define XLOG_ALL    (XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS)
  150. X
  151. X#ifdef DEBUG
  152. X#ifdef DEBUG_MEM
  153. X#define free(x) xfree(__FILE__,__LINE__,x)
  154. X#endif
  155. X
  156. X#define    DEBUG_MTAB    "./mtab"
  157. X
  158. Xextern int debug_flags;        /* Debug options */
  159. X
  160. X#define    D_DAEMON    0x0001    /* Enter daemon mode */
  161. X#define    D_TRACE        0x0002    /* Do protocol trace */
  162. X#define    D_FULL        0x0004    /* Do full trace */
  163. X#define    D_MTAB        0x0008    /* Use local mtab */
  164. X#define    D_AMQ        0x0010    /* Register amq program */
  165. X#define    D_STR        0x0020    /* Debug string munging */
  166. X#define    D_MEM        0x0040    /* Trace memory allocations */
  167. X
  168. X/*
  169. X * Normally, don't enter daemon mode, and don't register amq
  170. X */
  171. X#define    D_TEST    (~(D_DAEMON|D_MEM|D_STR))
  172. X#define    D_ALL    (~0)
  173. X
  174. X#define Debug(x) if (!(debug_flags & (x))) ; else
  175. X#define dlog Debug(D_FULL) dplog
  176. X#endif
  177. X
  178. Xtypedef enum {
  179. X    Start,
  180. X    Run,
  181. X    Finishing,
  182. X    Quit,
  183. X    Done
  184. X} serv_state;
  185. X
  186. Xextern serv_state amd_state;    /* Should we go now */
  187. Xextern int immediate_abort;    /* Should close-down unmounts be retried */
  188. Xextern time_t do_mapc_reload;    /* Flush & reload mount map cache */
  189. X
  190. X/*
  191. X * Useful constants
  192. X */
  193. Xextern char *progname;        /* "amd" */
  194. Xextern char pid_fsname[];    /* kiska.southseas.nz:(pid%d) */
  195. Xextern char hostname[];        /* "kiska" */
  196. Xextern char hostd[];        /* "kiska.southseas.nz" */
  197. Xextern char *hostdomain;    /* "southseas.nz" */
  198. Xextern char *op_sys;        /* "sos4" */
  199. Xextern char *arch;        /* "sun4" */
  200. Xextern char *karch;        /* "sun4c" */
  201. Xextern char *cluster;        /* "r+d-kluster" */
  202. Xextern char *endian;        /* "big" */
  203. Xextern char *auto_dir;        /* "/a" */
  204. Xextern char version[];        /* Version info */
  205. X
  206. Xtypedef struct am_ops am_ops;
  207. Xtypedef struct am_node am_node;
  208. Xtypedef struct am_opts am_opts;
  209. Xtypedef struct mntfs mntfs;
  210. Xtypedef struct fserver fserver;
  211. X
  212. X/*
  213. X * Global variables.
  214. X */
  215. Xextern unsigned short nfs_port;    /* Our NFS service port */
  216. Xextern int mypid;        /* Current process id */
  217. Xextern struct in_addr myipaddr;    /* (An) IP address of this host */
  218. X
  219. Xextern int foreground;        /* Foreground process */
  220. Xextern int orig_umask;        /* umask() on startup */
  221. X#define clocktime() (clock_valid ? clock_valid : time(&clock_valid))
  222. Xextern time_t time P((time_t *));
  223. Xextern time_t clock_valid;    /* Clock needs recalculating */
  224. Xextern time_t next_softclock;    /* Time to call softclock() */
  225. Xextern int task_notify_todo;    /* Task notifier needs running */
  226. X#ifdef HAS_TFS
  227. Xextern int nfs_server_code_available;
  228. X#endif
  229. Xextern int last_used_map;    /* Last map being used for mounts */
  230. Xextern AUTH *nfs_auth;        /* Dummy uthorisation for remote servers */
  231. Xextern am_node *exported_ap[];    /* List of nodes */
  232. Xextern int first_free_map;    /* First free node */
  233. X#define    NEXP_AP    (4 * NMOUNT)
  234. X
  235. Xtypedef int (*task_fun)P((voidp));
  236. Xtypedef void (*cb_fun)P((int, int, voidp));
  237. Xtypedef void (*fwd_fun)P((voidp, int, struct sockaddr_in *,
  238. X                struct sockaddr_in *, voidp, int));
  239. X
  240. X/*
  241. X * String comparison macros
  242. X */
  243. X#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
  244. X#define FSTREQ(s1, s2) ((*(s1) == *(s2)) && STREQ((s1),(s2)))
  245. X
  246. X/*
  247. X * Linked list
  248. X */
  249. Xtypedef struct qelem qelem;
  250. Xstruct qelem {
  251. X    qelem *q_forw;
  252. X    qelem *q_back;
  253. X};
  254. X#define    FIRST(ty, q)    ((ty *) ((q)->q_forw))
  255. X#define    LAST(ty, q)    ((ty *) ((q)->q_back))
  256. X#define    NEXT(ty, q)    ((ty *) (((qelem *) q)->q_forw))
  257. X#define    PREV(ty, q)    ((ty *) (((qelem *) q)->q_back))
  258. X#define    HEAD(ty, q)    ((ty *) q)
  259. X#define    ITER(v, ty, q) \
  260. X    for ((v) = FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
  261. X
  262. X/*
  263. X * List of mount table entries
  264. X */
  265. Xtypedef struct mntlist mntlist;
  266. Xstruct mntlist {
  267. X    struct mntlist *mnext;
  268. X    struct mntent *mnt;
  269. X};
  270. X
  271. X/*
  272. X * Mount map
  273. X */
  274. Xtypedef struct mnt_map mnt_map;
  275. X
  276. X/*
  277. X * Global routines
  278. X */
  279. Xextern int atoi P((const char *)); /* C */
  280. Xextern void am_mounted P((am_node*));
  281. Xextern void am_unmounted P((am_node*));
  282. Xextern int background(P_void);
  283. Xextern int bind_resv_port P((int, unsigned short*));
  284. Xextern int compute_mount_flags P((struct mntent *));
  285. Xextern int softclock(P_void);
  286. X#ifdef DEBUG
  287. Xextern int debug_option P((char*));
  288. Xextern void dplog ();
  289. X/*extern void dplog P((char*, ...));*/
  290. X#endif
  291. X/*extern void domain_strip P((char*, char*));*/
  292. Xextern mntfs* dup_mntfs P((mntfs*));
  293. Xextern fserver* dup_srvr P((fserver*));
  294. Xextern int eval_fs_opts P((am_opts*, char*, char*, char*, char*, char*));
  295. Xextern char* expand_key P((char*));
  296. Xextern am_node* exported_ap_alloc(P_void);
  297. Xextern am_node* find_ap P((char*));
  298. Xextern mntfs* find_mntfs P((am_ops*, am_opts*, char*, char*, char*));
  299. Xextern void flush_mntfs(P_void);
  300. Xextern void free P((voidp)); /* C */
  301. Xextern void free_mntfs P((mntfs*));
  302. Xextern void free_opts P((am_opts*));
  303. Xextern void free_map P((am_node*));
  304. Xextern void free_mntlist P((mntlist*));
  305. Xextern int fwd_init(P_void);
  306. Xextern int fwd_packet P((int, voidp, int, struct sockaddr_in *,
  307. X        struct sockaddr_in *, voidp, fwd_fun));
  308. Xextern void fwd_reply(P_void);
  309. Xextern void get_args P((int, char*[]));
  310. Xextern void going_down P((int));
  311. X#ifdef NEED_MNTOPT_PARSER
  312. Xextern char *hasmntopt P((struct mntent*, char*));
  313. X#endif
  314. Xextern int hasmntval P((struct mntent*, char*));
  315. Xextern void host_normalize P((char **));
  316. Xextern void init_map P((am_node*, char*));
  317. Xextern void insert_am P((am_node*, am_node*));
  318. Xextern void ins_que P((qelem*, qelem*));
  319. Xextern void make_root_node(P_void);
  320. Xextern int make_rpc_packet P((char*, int, u_long, struct rpc_msg*, voidp, xdrproc_t, AUTH*));
  321. Xextern void mapc_add_kv P((mnt_map*, char*, char*));
  322. Xextern mnt_map* mapc_find P((char*, char*));
  323. Xextern void mapc_free P((mnt_map*));
  324. Xextern int mapc_search P((mnt_map*, char*, char**));
  325. Xextern void mapc_reload(P_void);
  326. Xextern void mapc_showtypes P((FILE*));
  327. Xextern int mkdirs P((char*, int));
  328. Xextern void mnt_free P((struct mntent*));
  329. Xextern int mount_automounter P((int));
  330. Xextern int mount_exported(P_void);
  331. Xextern int mount_node P((am_node*));
  332. Xextern mntfs* new_mntfs(P_void);
  333. Xextern void new_ttl P((am_node*));
  334. Xextern am_node* next_map P((int*));
  335. Xextern int nfs_srvr_port P((fserver*, u_short*, voidp));
  336. Xextern int pickup_rpc_reply P((voidp, int, voidp, xdrproc_t));
  337. Xextern void plog ();
  338. X/*extern void plog P((int, char*, ...));*/
  339. Xextern mntlist* read_mtab P((char*));
  340. Xextern mntfs* realloc_mntfs  P((mntfs*, am_ops*, am_opts*, char*, char*, char*));
  341. Xextern void rem_que P((qelem*));
  342. Xextern void reschedule_timeout_mp(P_void);
  343. Xextern void restart(P_void);
  344. X#ifdef UPDATE_MTAB
  345. Xextern void rewrite_mtab P((mntlist *));
  346. X#endif
  347. Xextern void rmdirs P((char*));
  348. Xextern am_node* root_ap P((char*, int));
  349. Xextern void root_newmap P((char*, char*, char*));
  350. Xextern void rpc_msg_init P((struct rpc_msg*, u_long, u_long, u_long));
  351. Xextern void run_task P((task_fun, voidp, cb_fun, voidp));
  352. Xextern void sched_task P((cb_fun, voidp, voidp));
  353. Xextern void show_rcs_info P((const char*, char*));
  354. Xextern void sigchld P((int));
  355. Xextern char* str3cat P((char*, char*, char*, char*));
  356. Xextern char* strcat P((char*, const char*)); /* C */
  357. Xextern char* strchr P((const char*, int)); /* C */
  358. Xextern int strcmp P((const char*, const char*)); /* C */
  359. Xextern char* strdup P((const char*));
  360. Xextern int strlen P((const char*)); /* C */
  361. Xextern char* strnsave P((const char*, int));
  362. Xextern char* strrchr P((const char*, int)); /* C */
  363. Xextern char* strealloc P((char*, char *));
  364. Xextern char** strsplit P((char*, int));
  365. Xextern int switch_option P((char*));
  366. Xextern void task_notify(P_void);
  367. Xextern int timeout P((unsigned int, void (*fn)(), voidp));
  368. Xextern void timeout_mp(P_void);
  369. Xextern void umount_exported(P_void);
  370. X/*extern int unmount_node P((am_node*));
  371. Xextern int unmount_node_wrap P((voidp));*/
  372. Xextern void unregister_amq(P_void);
  373. Xextern void untimeout P((int));
  374. Xextern int valid_key P((char*));
  375. Xextern void wakeup P((voidp));
  376. Xextern void wakeup_task P((int,int,voidp));
  377. Xextern void wakeup_srvr P((fserver*));
  378. Xextern void write_mntent P((struct mntent*));
  379. Xextern voidp xmalloc P((int));
  380. Xextern voidp xrealloc P((voidp, int));
  381. X
  382. X#define    ALLOC(ty)    ((struct ty *) xmalloc(sizeof(struct ty)))
  383. X
  384. X/*
  385. X * Options
  386. X */
  387. Xstruct am_opts {
  388. X    char    *fs_glob;        /* Smashed copy of global options */
  389. X    char    *fs_local;        /* Expanded copy of local options */
  390. X    char    *fs_mtab;        /* Mount table entry */
  391. X    /* Other options ... */
  392. X    char    *opt_dev;
  393. X    char    *opt_delay;
  394. X    char    *opt_dir;
  395. X    char    *opt_fs;
  396. X    char    *opt_group;
  397. X    char    *opt_mount;
  398. X    char    *opt_opts;
  399. X    char    *opt_pref;
  400. X    char    *opt_cache;
  401. X    char    *opt_rfs;
  402. X    char    *opt_rhost;
  403. X    char    *opt_sublink;
  404. X    char    *opt_type;
  405. X    char    *opt_unmount;
  406. X    char    *opt_user;
  407. X};
  408. X
  409. X/*
  410. X * File Handle
  411. X *
  412. X * This is interpreted by indexing the exported array
  413. X * by fhh_id.
  414. X *
  415. X * The whole structure is mapped onto a standard fhandle_t
  416. X * when transmitted.
  417. X */
  418. Xstruct am_fh {
  419. X    int    fhh_pid;        /* process id */
  420. X    int    fhh_id;            /* map id */
  421. X    int    fhh_gen;        /* generation number */
  422. X};
  423. X
  424. Xextern am_node *fh_to_mp P((nfs_fh*));
  425. Xextern am_node *fh_to_mp3 P((nfs_fh*,int*,int));
  426. Xextern void mp_to_fh P((am_node*, nfs_fh*));
  427. X#define    fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
  428. X
  429. Xtypedef int    (*vfs_match)P((am_opts*));
  430. Xtypedef int    (*vfs_init)P((mntfs*));
  431. Xtypedef int    (*vmount_fs)P((am_node*));
  432. Xtypedef int    (*vumount_fs)P((am_node*));
  433. Xtypedef am_node*(*vlookuppn)P((am_node*, char*, int*, int));
  434. Xtypedef int    (*vreaddir)P((am_node*, nfscookie, dirlist*, entry*));
  435. Xtypedef char*    (*vreadlink)P((am_node*, int*));
  436. Xtypedef int    (*vmounted)P((mntfs*));
  437. Xtypedef void    (*vumounted)P((am_node*));
  438. Xtypedef fserver*(*vffserver)P((mntfs*));
  439. X
  440. Xstruct am_ops {
  441. X    char        *fs_type;
  442. X    vfs_match    fs_match;
  443. X    vfs_init    fs_init;
  444. X    vmount_fs    mount_fs;
  445. X    vumount_fs    umount_fs;
  446. X    vlookuppn    lookuppn;
  447. X    vreaddir    readdir;
  448. X    vreadlink    readlink;
  449. X    vmounted    mounted;
  450. X    vumounted    umounted;
  451. X    vffserver    ffserver;
  452. X    int        fs_flags;
  453. X    qelem        *srvr_list;
  454. X};
  455. Xextern am_node *efs_lookuppn P((am_node*, char*, int*, int));
  456. Xextern int efs_readdir P((am_node*, nfscookie, dirlist*, entry*));
  457. X
  458. X#define    VLOOK_CREATE    0x1
  459. X#define    VLOOK_DELETE    0x2
  460. X
  461. X#define    FS_RETRY    0x0001        /* Retry this type of mount */
  462. X#define    FS_MBACKGROUND    0x0002        /* Should background this mount */
  463. X#define    FS_NOTIMEOUT    0x0004        /* Don't bother with timeouts */
  464. X#define FS_MKMNT    0x0008        /* Need to make the mkdir point */
  465. X#define FS_UBACKGROUND    0x0010        /* Unmount in background */
  466. X#define    FS_BACKGROUND    (FS_MBACKGROUND|FS_UBACKGROUND)
  467. X#define    FS_DISCARD    0x0020        /* Discard immediately on last reference */
  468. X#define    FS_AMQINFO    0x0040        /* Amq is interested in this fs type */
  469. X
  470. X#ifdef SUNOS4_COMPAT
  471. Xextern am_ops *sunos4_match P((am_opts*, char*, char*, char*, char*, char*));
  472. X#endif
  473. Xextern am_ops *ops_match P((am_opts*, char*, char*, char*, char*, char*));
  474. X#include "fs.h"
  475. X
  476. X/*
  477. X * Per-mountpoint statistics
  478. X */
  479. Xstruct am_stats {
  480. X    time_t    s_mtime;    /* Mount time */
  481. X    u_short    s_uid;        /* Uid of mounter */
  482. X    int    s_getattr;    /* Count of getattrs */
  483. X    int    s_lookup;    /* Count of lookups */
  484. X    int    s_readdir;    /* Count of readdirs */
  485. X    int    s_readlink;    /* Count of readlinks */
  486. X    int    s_statfs;    /* Count of statfs */
  487. X};
  488. Xtypedef struct am_stats am_stats;
  489. X
  490. X/*
  491. X * System statistics
  492. X */
  493. Xstruct amd_stats {
  494. X    int    d_drops;    /* Dropped requests */
  495. X    int    d_stale;    /* Stale NFS handles */
  496. X    int    d_mok;        /* Succesful mounts */
  497. X    int    d_merr;        /* Failed mounts */
  498. X    int    d_uerr;        /* Failed unmounts */
  499. X};
  500. Xextern struct amd_stats amd_stats;
  501. X
  502. X/*
  503. X * List of fileservers
  504. X */
  505. Xstruct fserver {
  506. X    qelem        fs_q;        /* List of fileservers */
  507. X    int        fs_refc;    /* Number of references to this node */
  508. X    char        *fs_host;    /* Normalized hostname of server */
  509. X    struct sockaddr_in *fs_ip;    /* Network address of server */
  510. X    int        fs_cid;        /* Callout id */
  511. X    int        fs_pinger;    /* Ping (keepalive) interval */
  512. X    int        fs_flags;    /* Flags */
  513. X    voidp        fs_private;    /* Private data */
  514. X    void        (*fs_prfree)();    /* Free private data */
  515. X};
  516. X#define    FSF_VALID    0x0001        /* Valid information available */
  517. X#define    FSF_DOWN    0x0002        /* This fileserver is down */
  518. X#define    FSF_ERROR    0x0004        /* Permanent error has occured */
  519. X#define    FSF_WANT    0x0008        /* Want a wakeup call */
  520. X#define    FSF_PINGING    0x0010        /* Already doing pings */
  521. X#define    FSRV_ISDOWN(fs)    (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
  522. X
  523. X/*
  524. X * List of mounted filesystems
  525. X */
  526. Xstruct mntfs {
  527. X    qelem        mf_q;        /* List of mounted filesystems */
  528. X    am_ops        *mf_ops;    /* Operations on this mountpoint */
  529. X    am_opts        *mf_fo;        /* File opts */
  530. X    struct attrstat    mf_attr;    /* File attributes */
  531. X#define mf_fattr    mf_attr.attrstat_u.attributes
  532. X    char        *mf_mount;    /* "/a/kiska/home/kiska" */
  533. X    char        *mf_info;    /* Mount info */
  534. X    char        *mf_opts;    /* Mount opts */
  535. X    fserver        *mf_server;    /* File server */
  536. X    int        mf_flags;    /* Flags */
  537. X    int        mf_error;    /* Error code from background mount */
  538. X    int        mf_refc;    /* Number of references to this node */
  539. X    int        mf_cid;        /* Callout id */
  540. X    void        (*mf_prfree)();    /* Free private space */
  541. X    voidp        mf_private;    /* Private - per-fs data */
  542. X};
  543. X
  544. X#define    MFF_MOUNTED    0x0001        /* Node is mounted */
  545. X#define    MFF_MOUNTING    0x0002        /* Mount is in progress */
  546. X#define    MFF_UNMOUNTING    0x0004        /* Unmount is in progress */
  547. X#define    MFF_RESTART    0x0008        /* Restarted node */
  548. X#define MFF_MKMNT    0x0010        /* Delete this node's am_mount */
  549. X#define    MFF_ERROR    0x0020        /* This node failed to mount */
  550. X#define    MFF_LOGDOWN    0x0040        /* Logged that this mount is down */
  551. X#define    MFF_RSTKEEP    0x0080        /* Don't timeout this filesystem - restarted */
  552. X#define    MFF_WANTTIMO    0x0100        /* Need a timeout call when not busy */
  553. X
  554. X/*
  555. X * Map of auto-mount points.
  556. X */
  557. Xstruct am_node {
  558. X    int        am_mapno;    /* Map number */
  559. X    mntfs        *am_mnt;    /* Mounted filesystem */
  560. X    char        *am_name;    /* "kiska"
  561. X                       Name of this node */
  562. X    char        *am_path;    /* "/home/kiska"
  563. X                       Path of this node's mount point */
  564. X    char        *am_link;    /* "/a/kiska/home/kiska/this/that"
  565. X                       Link to sub-directory */
  566. X    am_node        *am_parent,    /* Parent of this node */
  567. X            *am_ysib,    /* Younger sibling of this node */
  568. X            *am_osib,    /* Older sibling of this node */
  569. X            *am_child;    /* First child of this node */
  570. X    int        am_flags;    /* Boolean flags */
  571. X    int        am_error;    /* Specific mount error */
  572. X    time_t        am_ttl;        /* Time to live */
  573. X    int        am_timeo_w;    /* Wait interval */
  574. X    int        am_timeo;    /* Timeout interval */
  575. X    unsigned int    am_gen;        /* Generation number */
  576. X    char        *am_pref;    /* Mount info prefix */
  577. X    am_stats    am_stats;    /* Statistics gathering */
  578. X};
  579. X
  580. X#define    AMF_NOTIMEOUT    0x0001        /* This node never times out */
  581. X#define    AMF_ROOT    0x0002        /* This is a root node */
  582. X#define AMF_MKPATH    0x0004        /* Delete this node's am_path */
  583. X
  584. X#define    ONE_HOUR    (60 * 60)    /* One hour in seconds */
  585. X
  586. X/*
  587. X * The following values can be tuned...
  588. X */
  589. X#define    ALLOWED_MOUNT_TIME    30        /* 30s for a mount */
  590. X#define    AM_TTL            (5 * 60)    /* Default cache period */
  591. X#define    AM_TTL_W        (2 * 60)    /* Default unmount interval */
  592. X#define    AM_PINGER        3        /* NFS ping interval */
  593. X#define    AFS_TIMEO        8        /* Default afs timeout - .8s */
  594. X#define    AFS_RETRANS        ((ALLOWED_MOUNT_TIME*10+2*afs_timeo)/afs_timeo)
  595. X                        /* Default afs timeout - 1/10th seconds */
  596. X
  597. X#define    RPC_XID_PORTMAP        0
  598. X#define    RPC_XID_MOUNTD        1
  599. X#define    RPC_XID_NFSPING        2
  600. X#define    RPC_XID_MASK        (0x0f)        /* 16 id's for now */
  601. X#define    MK_RPC_XID(type_id, uniq)    ((type_id) | ((uniq) << 4))
  602. END_OF_FILE
  603. if test 17876 -ne `wc -c <'am.h'`; then
  604.     echo shar: \"'am.h'\" unpacked with wrong size!
  605. fi
  606. # end of 'am.h'
  607. fi
  608. if test -f 'nfs_ops.c' -a "${1}" != "-c" ; then 
  609.   echo shar: Will not clobber existing file \"'nfs_ops.c'\"
  610. else
  611. echo shar: Extracting \"'nfs_ops.c'\" \(14835 characters\)
  612. sed "s/^X//" >'nfs_ops.c' <<'END_OF_FILE'
  613. X/*
  614. X * $Id: nfs_ops.c,v 5.1.1.2 90/01/11 17:12:34 jsp Exp Locker: jsp $
  615. X *
  616. X * Copyright (c) 1990 Jan-Simon Pendry
  617. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  618. X * Copyright (c) 1990 The Regents of the University of California.
  619. X * All rights reserved.
  620. X *
  621. X * This code is derived from software contributed to Berkeley by
  622. X * Jan-Simon Pendry at Imperial College, London.
  623. X *
  624. X * Redistribution and use in source and binary forms are permitted
  625. X * provided that the above copyright notice and this paragraph are
  626. X * duplicated in all such forms and that any documentation,
  627. X * advertising materials, and other materials related to such
  628. X * distribution and use acknowledge that the software was developed
  629. X * by Imperial College of Science, Technology and Medicine, London, UK.
  630. X * The names of the College and University may not be used to endorse
  631. X * or promote products derived from this software without specific
  632. X * prior written permission.
  633. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  634. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  635. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  636. X *
  637. X *    %W% (Berkeley) %G%
  638. X */
  639. X
  640. X#include "am.h"
  641. X
  642. X#ifdef HAS_NFS
  643. X
  644. X#define NFS
  645. X#define NFSCLIENT
  646. X#ifdef NFS_3
  647. Xtypedef nfs_fh fhandle_t;
  648. X#endif
  649. X#ifdef NFS_HDR
  650. X#include NFS_HDR
  651. X#endif
  652. X#include <sys/mount.h>
  653. X#include "mount.h"
  654. X
  655. X/*
  656. X * Network file system
  657. X */
  658. X
  659. X/*
  660. X * Convert from nfsstat to UN*X error code
  661. X */
  662. X#define unx_error(e)    ((int)(e))
  663. X
  664. X/*
  665. X * The NFS layer maintains a cache of file handles.
  666. X * This is *fundamental* to the implementation and
  667. X * also allows quick remounting when a filesystem
  668. X * is accessed soon after timing out.
  669. X *
  670. X * The NFS server layer knows to flush this cache
  671. X * when a server goes down so avoiding stale handles.
  672. X *
  673. X * Each cache entry keeps a hard reference to
  674. X * the corresponding server.  This ensures that
  675. X * the server keepalive information is maintained.
  676. X *
  677. X * The copy of the sockaddr_in here is taken so
  678. X * that the port can be twiddled to talk to mountd
  679. X * instead of portmap or the NFS server as used
  680. X * elsewhere.
  681. X * The port# is flushed if a server goes down.
  682. X * The IP address is never flushed - we assume
  683. X * that the address of a mounted machine never
  684. X * changes.  If it does, then you have other
  685. X * problems...
  686. X */
  687. Xtypedef struct fh_cache fh_cache;
  688. Xstruct fh_cache {
  689. X    qelem    fh_q;            /* List header */
  690. X    voidp    fh_wchan;        /* Wait channel */
  691. X    int    fh_error;        /* Valid data? */
  692. X    int    fh_id;            /* Unique id */
  693. X    int    fh_cid;            /* Callout id */
  694. X    struct fhstatus fh_handle;    /* Handle on filesystem */
  695. X    struct sockaddr_in fh_sin;    /* Address of mountd */
  696. X    fserver *fh_fs;            /* Server holding filesystem */
  697. X    char    *fh_path;        /* Filesystem on host */
  698. X};
  699. X
  700. X/*
  701. X * FH_TTL is the time a file handle will remain in the cache since
  702. X * last being used.  If the file handle becomes invalid, then it
  703. X * will be flushed anyway.
  704. X */
  705. X#define    FH_TTL        (5 * 60)        /* five minutes */
  706. X#define    FH_TTL_ERROR    (30)            /* 30 seconds */
  707. X
  708. Xstatic int fh_id = 0;
  709. X#define    FHID_ALLOC()    (++fh_id)
  710. Xextern qelem fh_head;
  711. Xqelem fh_head = { &fh_head, &fh_head };
  712. X
  713. Xstatic int call_mountd P((fh_cache*, unsigned long, fwd_fun, voidp));
  714. X
  715. XAUTH *nfs_auth;
  716. X
  717. Xstatic fh_cache *find_fhandle_cache P((voidp idv, int done));
  718. Xstatic fh_cache *find_fhandle_cache(idv, done)
  719. Xvoidp idv;
  720. Xint done;
  721. X{
  722. X    fh_cache *fp, *fp2 = 0;
  723. X    int id = (int) idv;
  724. X
  725. X    ITER(fp, fh_cache, &fh_head) {
  726. X        if (fp->fh_id == id) {
  727. X            fp2 = fp;
  728. X            break;
  729. X        }
  730. X    }
  731. X
  732. X#ifdef DEBUG
  733. X    if (fp2) {
  734. X        dlog("fh cache gives fp %#x, fs %s", fp2, fp2->fh_path);
  735. X    } else {
  736. X        dlog("fh cache search failed");
  737. X    }
  738. X#endif
  739. X
  740. X    if (fp2 && !done) {
  741. X        fp2->fh_error = ETIMEDOUT;
  742. X        return 0;
  743. X    }
  744. X
  745. X    return fp2;
  746. X}
  747. X
  748. X/*
  749. X * Called when a filehandle appears
  750. X */
  751. Xstatic void got_nfs_fh P((voidp pkt, int len, struct sockaddr_in *sa,
  752. X                struct sockaddr_in *ia, voidp idv, int done));
  753. Xstatic void got_nfs_fh(pkt, len, sa, ia, idv, done)
  754. Xvoidp pkt;
  755. Xint len;
  756. Xstruct sockaddr_in *sa, *ia;
  757. Xvoidp idv;
  758. Xint done;
  759. X{
  760. X    fh_cache *fp = find_fhandle_cache(idv, done);
  761. X    if (fp) {
  762. X        fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_handle, xdr_fhstatus);
  763. X        if (!fp->fh_error) {
  764. X#ifdef DEBUG
  765. X            dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
  766. X#endif
  767. X            /*
  768. X             * Wakeup anything sleeping on this filehandle
  769. X             */
  770. X            if (fp->fh_wchan) {
  771. X#ifdef DEBUG
  772. X                dlog("Calling wakeup on %#x", fp->fh_wchan);
  773. X#endif
  774. X                wakeup(fp->fh_wchan);
  775. X            }
  776. X        }
  777. X    }
  778. X}
  779. X
  780. Xvoid flush_fhandle_cache P((fserver *fs));
  781. Xvoid flush_fhandle_cache(fs)
  782. Xfserver *fs;
  783. X{
  784. X    fh_cache *fp;
  785. X    ITER(fp, fh_cache, &fh_head) {
  786. X        if (fp->fh_fs == fs) {
  787. X            fp->fh_sin.sin_port = (u_short) 0;
  788. X            fp->fh_error = -1;
  789. X        }
  790. X    }
  791. X}
  792. X
  793. Xstatic void discard_fh P((fh_cache *fp));
  794. Xstatic void discard_fh(fp)
  795. Xfh_cache *fp;
  796. X{
  797. X    rem_que(&fp->fh_q);
  798. X#ifdef DEBUG
  799. X    dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
  800. X#endif
  801. X    free_srvr(fp->fh_fs);
  802. X    free(fp->fh_path);
  803. X    free(fp);
  804. X}
  805. X
  806. X/*
  807. X * Determine the file handle for a node
  808. X */
  809. Xstatic int prime_fhandle_cache P((char *path, fserver *fs, struct fhstatus *fhbuf, voidp wchan));
  810. Xstatic int prime_fhandle_cache(path, fs, fhbuf, wchan)
  811. Xchar *path;
  812. Xfserver *fs;
  813. Xstruct fhstatus *fhbuf;
  814. Xvoidp wchan;
  815. X{
  816. X    fh_cache *fp, *fp_save = 0;
  817. X    int error;
  818. X    int reuse_id = FALSE;
  819. X
  820. X#ifdef DEBUG
  821. X    dlog("Searching cache for %s:%s", fs->fs_host, path);
  822. X#endif
  823. X
  824. X    /*
  825. X     * First search the cache
  826. X     */
  827. X    ITER(fp, fh_cache, &fh_head) {
  828. X        if (fs == fp->fh_fs && strcmp(path, fp->fh_path) == 0) {
  829. X            switch (fp->fh_error) {
  830. X            case 0:
  831. X                error = fp->fh_error = unx_error(fp->fh_handle.fhs_status);
  832. X                if (error == 0) {
  833. X                    if (fhbuf)
  834. X                        bcopy((voidp) &fp->fh_handle, (voidp) fhbuf,
  835. X                            sizeof(fp->fh_handle));
  836. X                    if (fp->fh_cid)
  837. X                        untimeout(fp->fh_cid);
  838. X                    fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
  839. X                } else if (error == EACCES) {
  840. X                    /*
  841. X                     * Now decode the file handle return code.
  842. X                     */
  843. X                    plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
  844. X                        fs->fs_host, path);
  845. X                } else {
  846. X                    errno = error;    /* XXX */
  847. X                    plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
  848. X                        fs->fs_host, path);
  849. X                }
  850. X
  851. X                /*
  852. X                 * The error was returned from the remote mount daemon.
  853. X                 * Policy: this error will be cached for now...
  854. X                 */
  855. X                return error;
  856. X
  857. X            case -1:
  858. X                /*
  859. X                 * Still thinking about it, but we can re-use.
  860. X                 */
  861. X                fp_save = fp;
  862. X                reuse_id = TRUE;
  863. X                break;
  864. X
  865. X            default:
  866. X                /*
  867. X                 * Return the error.
  868. X                 * Policy: make sure we recompute if required again
  869. X                 * in case this was caused by a network failure.
  870. X                 * This can thrash mountd's though...  If you find
  871. X                 * your mountd going slowly then:
  872. X                 * 1.  Add a fork() loop to main.
  873. X                 * 2.  Remove the call to innetgr() and don't use
  874. X                 *     netgroups, especially if you don't use YP.
  875. X                 */
  876. X                error = fp->fh_error;
  877. X                fp->fh_error = -1;
  878. X                return error;
  879. X            }
  880. X            break;
  881. X        }
  882. X    }
  883. X
  884. X    /*
  885. X     * Not in cache
  886. X     */
  887. X    if (fp_save) {
  888. X        fp = fp_save;
  889. X        /*
  890. X         * Re-use existing slot
  891. X         */
  892. X        untimeout(fp->fh_cid);
  893. X        free_srvr(fp->fh_fs);
  894. X        free(fp->fh_path);
  895. X    } else {
  896. X        fp = ALLOC(fh_cache);
  897. X        bzero((voidp) fp, sizeof(*fp));
  898. X        ins_que(&fp->fh_q, &fh_head);
  899. X    }
  900. X    if (!reuse_id)
  901. X        fp->fh_id = FHID_ALLOC();
  902. X    fp->fh_wchan = wchan;
  903. X    fp->fh_error = -1;
  904. X    fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
  905. X
  906. X    /*
  907. X     * If the address has changed then don't try to re-use the
  908. X     * port information
  909. X     */
  910. X    if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
  911. X        fp->fh_sin = *fs->fs_ip;
  912. X        fp->fh_sin.sin_port = 0;
  913. X    }
  914. X    fp->fh_fs = dup_srvr(fs);
  915. X    fp->fh_path = strdup(path);
  916. X
  917. X    error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);
  918. X    if (error) {
  919. X        /*
  920. X         * Local error - cache for a short period
  921. X         * just to prevent thrashing.
  922. X         */
  923. X        untimeout(fp->fh_cid);
  924. X        fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
  925. X                        discard_fh, (voidp) fp);
  926. X        fp->fh_error = error;
  927. X    } else {
  928. X        error = fp->fh_error;
  929. X    }
  930. X    return error;
  931. X}
  932. X
  933. Xstatic int call_mountd P((fh_cache *fp, u_long proc, fwd_fun f, voidp wchan));
  934. Xstatic int call_mountd(fp, proc, f, wchan)
  935. Xfh_cache *fp;
  936. Xu_long proc;
  937. Xfwd_fun f;
  938. Xvoidp wchan;
  939. X{
  940. X    struct rpc_msg mnt_msg;
  941. X    int len;
  942. X    char iobuf[8192];
  943. X    int error;
  944. X
  945. X    if (!nfs_auth) {
  946. X        nfs_auth = authunix_create_default();
  947. X        if (!nfs_auth)
  948. X            return ENOBUFS;
  949. X    }
  950. X
  951. X    if (fp->fh_sin.sin_port == 0) {
  952. X        u_short port;
  953. X        error = nfs_srvr_port(fp->fh_fs, &port, wchan);
  954. X        if (error)
  955. X            return error;
  956. X        fp->fh_sin.sin_port = port;
  957. X    }
  958. X
  959. X    rpc_msg_init(&mnt_msg, MOUNTPROG, MOUNTVERS, (unsigned long) 0);
  960. X    len = make_rpc_packet(iobuf, sizeof(iobuf), proc,
  961. X            &mnt_msg, (voidp) &fp->fh_path, xdr_nfspath,  nfs_auth);
  962. X
  963. X    if (len > 0) {
  964. X        error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
  965. X            (voidp) iobuf, len, &fp->fh_sin, &fp->fh_sin, (voidp) fp->fh_id, f);
  966. X    } else {
  967. X        error = -len;
  968. X    }
  969. X    return error;
  970. X}
  971. X
  972. X/*-------------------------------------------------------------------------*/
  973. X
  974. X/*
  975. X * NFS needs the local filesystem, remote filesystem
  976. X * remote hostname.
  977. X * Local filesystem defaults to remote and vice-versa.
  978. X */
  979. Xstatic int nfs_match(fo)
  980. Xam_opts *fo;
  981. X{
  982. X    if (fo->opt_fs && !fo->opt_rfs)
  983. X        fo->opt_rfs = fo->opt_fs;
  984. X    if (!fo->opt_rfs) {
  985. X        plog(XLOG_USER, "nfs: no remote filesystem specified");
  986. X        return 0;
  987. X    }
  988. X    if (!fo->opt_rhost) {
  989. X        plog(XLOG_USER, "nfs: no remote host specified");
  990. X        return 0;
  991. X    }
  992. X    /*
  993. X     * Determine magic cookie to put in mtab
  994. X     */
  995. X    fo->fs_mtab = (char *) xrealloc(fo->fs_mtab, strlen(fo->opt_rhost) +
  996. X                strlen(fo->opt_rfs) + 2);
  997. X    sprintf(fo->fs_mtab, "%s:%s", fo->opt_rhost, fo->opt_rfs);
  998. X#ifdef DEBUG
  999. X    dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
  1000. X        fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
  1001. X#endif
  1002. X
  1003. X    return 1;
  1004. X}
  1005. X
  1006. X/*
  1007. X * Initialise am structure for nfs
  1008. X */
  1009. Xstatic int nfs_init(mf)
  1010. Xmntfs *mf;
  1011. X{
  1012. X    int error;
  1013. X    char *colon = strchr(mf->mf_info, ':');
  1014. X    if (colon == 0)
  1015. X        return ENOENT;
  1016. X
  1017. X    error = prime_fhandle_cache(colon+1, mf->mf_server, (struct fhstatus *) 0, (voidp) mf);
  1018. X
  1019. X    return error;
  1020. X}
  1021. X
  1022. Xstatic mount_nfs(dir, fs_name, opts, mf)
  1023. Xchar *dir;
  1024. Xchar *fs_name;
  1025. Xchar *opts;
  1026. Xmntfs *mf;
  1027. X{
  1028. X    struct nfs_args nfs_args;
  1029. X    struct mntent mnt;
  1030. X    int retry;
  1031. X    struct fhstatus fhs;
  1032. X    int error;
  1033. X    char *colon;
  1034. X    char *path;
  1035. X    char host[MAXHOSTNAMELEN + MAXPATHLEN + 2];
  1036. X    fserver *fs = mf->mf_server;
  1037. X    int flags;
  1038. X#ifdef notdef
  1039. X    unsigned short port;
  1040. X#endif
  1041. X
  1042. X    MTYPE_TYPE type = MOUNT_TYPE_NFS;
  1043. X
  1044. X    bzero((voidp) &nfs_args, sizeof(nfs_args));    /* Paranoid */
  1045. X
  1046. X    /*
  1047. X     * Extract host name to give to kernel
  1048. X     */
  1049. X    if (!(colon = strchr(fs_name, ':')))
  1050. X        return ENOENT;
  1051. X#ifndef NFS_ARGS_NEEDS_PATH
  1052. X    *colon = '\0';
  1053. X#endif
  1054. X    strncpy(host, fs_name, sizeof(host));
  1055. X#ifndef NFS_ARGS_NEEDS_PATH
  1056. X    *colon = ':';
  1057. X#endif
  1058. X    path = colon + 1;
  1059. X
  1060. X    bzero((voidp) &nfs_args, sizeof(nfs_args));
  1061. X
  1062. X    mnt.mnt_dir = dir;
  1063. X    mnt.mnt_fsname = fs_name;
  1064. X    mnt.mnt_type = MTAB_TYPE_NFS;
  1065. X    mnt.mnt_opts = opts;
  1066. X    mnt.mnt_freq = 0;
  1067. X    mnt.mnt_passno = 0;
  1068. X
  1069. X    retry = hasmntval(&mnt, "retry");
  1070. X    if (retry <= 0)
  1071. X        retry = 1;    /* XXX */
  1072. X
  1073. X/*again:*/
  1074. X#ifdef DEBUG
  1075. X    dlog("locating fhandle for %s", fs_name);
  1076. X#endif
  1077. X    error = prime_fhandle_cache(path, mf->mf_server, &fhs, (voidp) 0);
  1078. X
  1079. X    if (error)
  1080. X        return error;
  1081. X
  1082. X    /*
  1083. X     * set mount args
  1084. X     */
  1085. X    nfs_args.fh = (NFS_FH_TYPE) fhs.fhstatus_u.fhs_fhandle;
  1086. X
  1087. X#ifdef ULTRIX_HACK
  1088. X    nfs_args.optstr = mnt.mnt_opts;
  1089. X#endif
  1090. X
  1091. X    nfs_args.hostname = host;
  1092. X    nfs_args.flags |= NFSMNT_HOSTNAME;
  1093. X#ifdef HOSTNAMESZ
  1094. X    /*
  1095. X     * Most kernels have a name length restriction.
  1096. X     */
  1097. X    if (strlen(host) >= HOSTNAMESZ)
  1098. X        strcpy(host + HOSTNAMESZ - 3, "..");
  1099. X#endif
  1100. X
  1101. X    if (nfs_args.rsize = hasmntval(&mnt, "rsize"))
  1102. X        nfs_args.flags |= NFSMNT_RSIZE;
  1103. X
  1104. X    if (nfs_args.wsize = hasmntval(&mnt, "wsize"))
  1105. X        nfs_args.flags |= NFSMNT_WSIZE;
  1106. X
  1107. X    if (nfs_args.timeo = hasmntval(&mnt, "timeo"))
  1108. X        nfs_args.flags |= NFSMNT_TIMEO;
  1109. X
  1110. X    if (nfs_args.retrans = hasmntval(&mnt, "retrans"))
  1111. X        nfs_args.flags |= NFSMNT_RETRANS;
  1112. X
  1113. X#ifdef notdef
  1114. X/*
  1115. X * This isn't supported by the ping algorithm yet.
  1116. X * In any case, it is all done in nfs_init().
  1117. X */
  1118. X     if (port = hasmntval(&mnt, "port"))
  1119. X        sin.sin_port = htons(port);
  1120. X    else
  1121. X        sin.sin_port = htons(NFS_PORT);    /* XXX should use portmapper */
  1122. X#endif
  1123. X
  1124. X    if (hasmntopt(&mnt, MNTOPT_SOFT) != NULL)
  1125. X        nfs_args.flags |= NFSMNT_SOFT;
  1126. X
  1127. X#ifdef MNTOPT_INTR
  1128. X    if (hasmntopt(&mnt, MNTOPT_INTR) != NULL)
  1129. X        nfs_args.flags |= NFSMNT_INT;
  1130. X#endif
  1131. X
  1132. X#ifdef MNTOPT_NODEVS
  1133. X    if (hasmntopt(&mnt, MNTOPT_NODEVS) != NULL)
  1134. X        nfs_args.flags |= NFSMNT_NODEVS;
  1135. X#endif
  1136. X
  1137. X#ifdef NFSMNT_PGTHRESH
  1138. X    if (nfs_args.pg_thresh = hasmntval(&mnt, "pgthresh"))
  1139. X        nfs_args.flags |= NFSMNT_PGTHRESH;
  1140. X#endif
  1141. X
  1142. X    nfs_args.addr = fs->fs_ip;
  1143. X
  1144. X    flags = compute_mount_flags(&mnt);
  1145. X
  1146. X#ifdef ULTRIX_HACK
  1147. X    /*
  1148. X     * Ultrix passes the flags argument as part of the
  1149. X     * mount data structure, rather than using the
  1150. X     * flags argument to the system call.  This is
  1151. X     * confusing...
  1152. X     */
  1153. X    if (!(nfs_args.flags & NFSMNT_PGTHRESH)) {
  1154. X        nfs_args.pg_thresh = 64; /* 64k - XXX */
  1155. X        nfs_args.flags |= NFSMNT_PGTHRESH;
  1156. X    }
  1157. X    nfs_args.gfs_flags = flags;
  1158. X    flags &= M_RDONLY;
  1159. X    if (flags & M_RDONLY)
  1160. X        nfs_args.flags |= NFSMNT_RONLY;
  1161. X#endif
  1162. X
  1163. X    return mount_fs(&mnt, flags, (caddr_t) &nfs_args, retry, type);
  1164. X}
  1165. X
  1166. Xstatic int nfs_mount(mp)
  1167. Xam_node *mp;
  1168. X{
  1169. X    mntfs *mf = mp->am_mnt;
  1170. X
  1171. X    int error = mount_nfs(mf->mf_mount, mf->mf_info,
  1172. X            mf->mf_fo->opt_opts, mf);
  1173. X
  1174. X#ifdef DEBUG
  1175. X    if (error) {
  1176. X        errno = error;
  1177. X        dlog("mount_nfs: %m");
  1178. X    }
  1179. X#endif
  1180. X    return error;
  1181. X}
  1182. X
  1183. Xstatic int nfs_umount(mp)
  1184. Xam_node *mp;
  1185. X{
  1186. X    mntfs *mf = mp->am_mnt;
  1187. X
  1188. X    int error = UMOUNT_FS(mf->mf_mount);
  1189. X    if (error)
  1190. X        return error;
  1191. X
  1192. X    return 0;
  1193. X}
  1194. X
  1195. Xstatic void nfs_umounted(mp)
  1196. Xam_node *mp;
  1197. X{
  1198. X#ifdef INFORM_MOUNTD
  1199. X    /*
  1200. X     * Don't bother to inform remote mountd
  1201. X     * that we are finished.  Until a full
  1202. X     * track of filehandles is maintained
  1203. X     * the mountd unmount callback cannot
  1204. X     * be done correctly anyway...
  1205. X     */
  1206. X
  1207. X    mntfs *mf = mp->am_mnt;
  1208. X    fserver *fs;
  1209. X    char *colon, *path;
  1210. X
  1211. X    if (mf->mf_error || mf->mf_refc > 1)
  1212. X        return;
  1213. X
  1214. X    fs = mf->mf_server;
  1215. X
  1216. X    /*
  1217. X     * Call the mount daemon on the server to
  1218. X     * announce that we are not using the fs any more.
  1219. X     *
  1220. X     * This is *wrong*.  The mountd should be called
  1221. X     * when the fhandle is flushed from the cache, and
  1222. X     * a reference held to the cached entry while the
  1223. X     * fs is mounted...
  1224. X     */
  1225. X    colon = path = strchr(mf->mf_info, ':');
  1226. X    if (fs && colon) {
  1227. X        fh_cache f;
  1228. X#ifdef DEBUG
  1229. X        dlog("calling mountd for %s", mf->mf_info);
  1230. X#endif
  1231. X        *path++ = '\0';
  1232. X        f.fh_path = path;
  1233. X        f.fh_sin = *fs->fs_ip;
  1234. X        f.fh_sin.sin_port = (u_short) 0;
  1235. X        f.fh_fs = fs;
  1236. X        f.fh_id = 0;
  1237. X        f.fh_error = 0;
  1238. X        (void) prime_fhandle_cache(colon+1, mf->mf_server, (struct fhstatus *) 0, (voidp) mf);
  1239. X        (void) call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun) 0, (voidp) 0);
  1240. X        *colon = ':';
  1241. X    }
  1242. X#endif
  1243. X}
  1244. X
  1245. X/*
  1246. X * Network file system
  1247. X */
  1248. Xam_ops nfs_ops = {
  1249. X    "nfs",
  1250. X    nfs_match,
  1251. X    nfs_init,
  1252. X    nfs_mount,
  1253. X    nfs_umount,
  1254. X    efs_lookuppn,
  1255. X    efs_readdir,
  1256. X    0, /* nfs_readlink */
  1257. X    0, /* nfs_mounted */
  1258. X    nfs_umounted,
  1259. X    find_nfs_srvr,
  1260. X    FS_MKMNT|FS_BACKGROUND|FS_AMQINFO,
  1261. X    &nfs_srvr_list,
  1262. X};
  1263. X
  1264. X#endif /* HAS_NFS */
  1265. END_OF_FILE
  1266. if test 14835 -ne `wc -c <'nfs_ops.c'`; then
  1267.     echo shar: \"'nfs_ops.c'\" unpacked with wrong size!
  1268. fi
  1269. # end of 'nfs_ops.c'
  1270. fi
  1271. if test -f 'util.c' -a "${1}" != "-c" ; then 
  1272.   echo shar: Will not clobber existing file \"'util.c'\"
  1273. else
  1274. echo shar: Extracting \"'util.c'\" \(15603 characters\)
  1275. sed "s/^X//" >'util.c' <<'END_OF_FILE'
  1276. X/*
  1277. X * $Id: util.c,v 5.1.1.3 90/01/11 17:23:29 jsp Exp Locker: jsp $
  1278. X *
  1279. X * Copyright (c) 1990 Jan-Simon Pendry
  1280. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  1281. X * Copyright (c) 1990 The Regents of the University of California.
  1282. X * All rights reserved.
  1283. X *
  1284. X * This code is derived from software contributed to Berkeley by
  1285. X * Jan-Simon Pendry at Imperial College, London.
  1286. X *
  1287. X * Redistribution and use in source and binary forms are permitted
  1288. X * provided that the above copyright notice and this paragraph are
  1289. X * duplicated in all such forms and that any documentation,
  1290. X * advertising materials, and other materials related to such
  1291. X * distribution and use acknowledge that the software was developed
  1292. X * by Imperial College of Science, Technology and Medicine, London, UK.
  1293. X * The names of the College and University may not be used to endorse
  1294. X * or promote products derived from this software without specific
  1295. X * prior written permission.
  1296. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1297. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1298. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1299. X *
  1300. X *    %W% (Berkeley) %G%
  1301. X */
  1302. X
  1303. X/*
  1304. X * Utils
  1305. X */
  1306. X
  1307. X#include "am.h"
  1308. X#ifdef HAS_SYSLOG
  1309. X#include <syslog.h>
  1310. X#endif
  1311. X#include <ctype.h>
  1312. X#include <sys/stat.h>
  1313. X
  1314. X#include <netdb.h>
  1315. X
  1316. X
  1317. XINLINE
  1318. Xchar *strnsave(str, len)
  1319. Xconst char *str;
  1320. Xint len;
  1321. X{
  1322. X    char *sp = (char *) xmalloc(len+1);
  1323. X
  1324. X    bcopy(str, sp, len);
  1325. X    sp[len] = 0;
  1326. X
  1327. X    return sp;
  1328. X}
  1329. X
  1330. Xchar *strdup(s)
  1331. Xconst char *s;
  1332. X{
  1333. X    return strnsave(s, strlen(s));
  1334. X}
  1335. X
  1336. X/*
  1337. X * Concatenate three strings and store in buffer pointed to
  1338. X * by p, making p large enough to hold the strings
  1339. X */
  1340. Xchar *str3cat(p, s1, s2, s3)
  1341. Xchar *p;
  1342. Xchar *s1;
  1343. Xchar *s2;
  1344. Xchar *s3;
  1345. X{
  1346. X    int l1 = strlen(s1);
  1347. X    int l2 = strlen(s2);
  1348. X    int l3 = strlen(s3);
  1349. X    p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
  1350. X    bcopy(s1, p, l1);
  1351. X    bcopy(s2, p + l1, l2);
  1352. X    bcopy(s3, p + l1 + l2, l3 + 1);
  1353. X    return p;
  1354. X}
  1355. X
  1356. Xchar *strealloc(p, s)
  1357. Xchar *p;
  1358. Xchar *s;
  1359. X{
  1360. X    int len = strlen(s) + 1;
  1361. X
  1362. X    p = (char *) xrealloc((voidp) p, len);
  1363. X
  1364. X    strcpy(p, s);
  1365. X#ifdef DEBUG_MEM
  1366. X    malloc_verify();
  1367. X#endif
  1368. X    return p;
  1369. X}
  1370. X
  1371. Xvoidp xrealloc(ptr, len)
  1372. Xvoidp ptr;
  1373. Xint len;
  1374. X{
  1375. X#if defined(DEBUG) && defined(DEBUG_MEM)
  1376. X    Debug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
  1377. X#endif
  1378. X
  1379. X    if (ptr)
  1380. X        ptr = (voidp) realloc(ptr, (unsigned) len);
  1381. X    else
  1382. X        ptr = (voidp) xmalloc((unsigned) len);
  1383. X
  1384. X    if (!ptr) {
  1385. X        plog(XLOG_FATAL, "Out of memory in realloc");
  1386. X        going_down(1);
  1387. X        abort();
  1388. X    }
  1389. X    return ptr;
  1390. X}
  1391. X
  1392. Xchar **strsplit(s, qc)
  1393. Xchar *s;
  1394. Xint qc;
  1395. X{
  1396. X    char **ivec;
  1397. X    int ic = 0;
  1398. X    int done = 0;
  1399. X
  1400. X    ivec = (char **) xmalloc((ic+1)*sizeof(char *));
  1401. X
  1402. X    while (!done) {
  1403. X        char *v;
  1404. X        /*
  1405. X         * skip white space
  1406. X         */
  1407. X        while (*s && isascii(*s) && isspace(*s))
  1408. X            s++;
  1409. X
  1410. X        /*
  1411. X         * End of string?
  1412. X         */
  1413. X        if (!*s)
  1414. X            break;
  1415. X
  1416. X        /*
  1417. X         * remember start of string
  1418. X         */
  1419. X        v = s;
  1420. X
  1421. X        /*
  1422. X         * skip to white space
  1423. X         */
  1424. X        while (*s && (!isascii(*s) || !isspace(*s))) {
  1425. X            if (*s++ == qc) {
  1426. X                /*
  1427. X                 * Skip past string.
  1428. X                 */
  1429. X                s++;
  1430. X                while (*s && *s != qc)
  1431. X                     s++;
  1432. X                if (*s == qc)
  1433. X                    s++;
  1434. X            }
  1435. X        }
  1436. X
  1437. X        if (!*s)
  1438. X            done = 1;
  1439. X        *s++ = '\0';
  1440. X
  1441. X        /*
  1442. X         * save string in new ivec slot
  1443. X         */
  1444. X        ivec[ic++] = v;
  1445. X        ivec = (char **) xrealloc(ivec, (ic+1)*sizeof(char *));
  1446. X#ifdef DEBUG
  1447. X        Debug(D_STR)
  1448. X            plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
  1449. X#endif
  1450. X    }
  1451. X
  1452. X#ifdef DEBUG
  1453. X    Debug(D_STR)
  1454. X        plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
  1455. X#endif
  1456. X
  1457. X    ivec[ic] = 0;
  1458. X
  1459. X    return ivec;
  1460. X}
  1461. X
  1462. X/*
  1463. X * Strip off the trailing part of a domain
  1464. X * to produce a short-form domain relative
  1465. X * to the local host domain.
  1466. X * Note that this has no effect if the domain
  1467. X * names do not have the same number of
  1468. X * components.  If that restriction proves
  1469. X * to be a problem then the loop needs recoding
  1470. X * to skip from right to left and do partial
  1471. X * matches along the way -- ie more expensive.
  1472. X */
  1473. Xstatic void domain_strip P((char *otherdom, char *localdom));
  1474. Xstatic void domain_strip(otherdom, localdom)
  1475. Xchar *otherdom, *localdom;
  1476. X{
  1477. X        char *p1 = otherdom-1;
  1478. X    char *p2 = localdom-1;
  1479. X
  1480. X        do {
  1481. X                if (p1 = strchr(p1+1, '.'))
  1482. X                if (p2 = strchr(p2+1, '.'))
  1483. X                if (strcmp(p1+1, p2+1) == 0) {
  1484. X                        *p1 = '\0';
  1485. X                        break;
  1486. X                }
  1487. X        } while (p1 && p2);
  1488. X}
  1489. X
  1490. X/*
  1491. X * Normalize a host name
  1492. X */
  1493. Xvoid host_normalize P((char **chp));
  1494. Xvoid host_normalize(chp)
  1495. Xchar **chp;
  1496. X{
  1497. X    /*
  1498. X     * Normalize hosts is used to resolve host name aliases
  1499. X     * and replace them with the standard-form name.
  1500. X     * Invoked with "-n" command line option.
  1501. X     */
  1502. X    if (normalize_hosts) {
  1503. X        struct hostent *hp;
  1504. X        clock_valid = 0;
  1505. X        hp = gethostbyname(*chp);
  1506. X        if (hp && hp->h_addrtype == AF_INET) {
  1507. X#ifdef DEBUG
  1508. X            dlog("Hostname %s normalized to %s", *chp, hp->h_name);
  1509. X#endif
  1510. X            *chp = strealloc(*chp, hp->h_name);
  1511. X        }
  1512. X    }
  1513. X    domain_strip(*chp, hostd);
  1514. X}
  1515. X
  1516. X/*
  1517. X * Keys are not allowed to contain " ' ! or ; to avoid
  1518. X * problems with macro expansions.
  1519. X */
  1520. Xstatic char invalid_keys[] = "\"'!;@ \t\n";
  1521. Xint valid_key P((char *key));
  1522. Xint valid_key(key)
  1523. Xchar *key;
  1524. X{
  1525. X    while (*key)
  1526. X        if (strchr(invalid_keys, *key++))
  1527. X            return FALSE;
  1528. X    return TRUE;
  1529. X}
  1530. X
  1531. Xvoid going_down P((int rc));
  1532. Xvoid going_down(rc)
  1533. Xint rc;
  1534. X{
  1535. X    if (foreground) {
  1536. X        if (amd_state != Start) {
  1537. X            if (amd_state != Done)
  1538. X                return;
  1539. X            unregister_amq();
  1540. X        }
  1541. X    }
  1542. X    if (foreground) {
  1543. X        plog(XLOG_INFO, "Finishing with status %d", rc);
  1544. X    } else {
  1545. X#ifdef DEBUG
  1546. X        dlog("background process exiting with status %d", rc);
  1547. X#endif
  1548. X    }
  1549. X
  1550. X    exit(rc);
  1551. X}
  1552. X
  1553. X#ifdef DEBUG_MEM
  1554. Xstatic int mem_bytes;
  1555. Xstatic int orig_mem_bytes;
  1556. Xstatic void checkup_mem(P_void)
  1557. X{
  1558. Xextern struct mallinfo __mallinfo;
  1559. X    if (mem_bytes != __mallinfo.uordbytes) {
  1560. X        if (orig_mem_bytes == 0)
  1561. X            mem_bytes = orig_mem_bytes = __mallinfo.uordbytes;
  1562. X        else {
  1563. X            fprintf(logfp, "%s[%d]: ", progname, mypid);
  1564. X            if (mem_bytes < __mallinfo.uordbytes) {
  1565. X                fprintf(logfp, "ALLOC: %d bytes",
  1566. X                    __mallinfo.uordbytes - mem_bytes);
  1567. X            } else {
  1568. X                fprintf(logfp, "FREE: %d bytes",
  1569. X                    mem_bytes - __mallinfo.uordbytes);
  1570. X            }
  1571. X            mem_bytes = __mallinfo.uordbytes;
  1572. X            fprintf(logfp, ", making %d missing\n",
  1573. X                mem_bytes - orig_mem_bytes);
  1574. X        }
  1575. X    }
  1576. X    malloc_verify();
  1577. X}
  1578. X#endif
  1579. X
  1580. X/*
  1581. X * Take a log format string and expand occurences of %m
  1582. X * with the current error code take from errno.
  1583. X */
  1584. XINLINE
  1585. Xstatic void expand_error(f, e)
  1586. Xchar *f;
  1587. Xchar *e;
  1588. X{
  1589. X    extern int sys_nerr;
  1590. X    extern char *sys_errlist[];
  1591. X    char *p;
  1592. X    int error = errno;
  1593. X
  1594. X    for (p = f; *e = *p; e++, p++) {
  1595. X        if (p[0] == '%' && p[1] == 'm') {
  1596. X            char *errstr;
  1597. X            if (error < 0 || error >= sys_nerr)
  1598. X                errstr = 0;
  1599. X            else
  1600. X                errstr = sys_errlist[error];
  1601. X            if (errstr)
  1602. X                strcpy(e, errstr);
  1603. X            else
  1604. X                sprintf(e, "Error %d", error);
  1605. X            e += strlen(e) - 1;
  1606. X            p++;
  1607. X        }
  1608. X    }
  1609. X}
  1610. X
  1611. X/*
  1612. X * Output the time of day and hostname to the logfile
  1613. X */
  1614. Xstatic void show_time_host_and_name(lvl)
  1615. Xint lvl;
  1616. X{
  1617. Xstatic time_t last_t = 0;
  1618. Xstatic char *last_ctime = 0;
  1619. X    time_t t = clocktime();
  1620. X    char *sev;
  1621. X    extern char *ctime();
  1622. X
  1623. X#if defined(DEBUG) && defined(PARANOID)
  1624. Xextern char **gargv;
  1625. X#endif
  1626. X
  1627. X    if (t != last_t) {
  1628. X        last_ctime = ctime(&t);
  1629. X        last_t = t;
  1630. X    }
  1631. X
  1632. X    switch (lvl) {
  1633. X    case XLOG_FATAL:    sev = "fatal:"; break;
  1634. X    case XLOG_ERROR:     sev = "error:"; break;
  1635. X    case XLOG_USER:        sev = "user: "; break;
  1636. X    case XLOG_WARNING:    sev = "warn: "; break;
  1637. X    case XLOG_INFO:        sev = "info: "; break;
  1638. X    case XLOG_DEBUG:    sev = "debug:"; break;
  1639. X    case XLOG_MAP:        sev = "map:  "; break;
  1640. X    case XLOG_STATS:    sev = "stats:"; break;
  1641. X    default:        sev = "hmm:  "; break;
  1642. X    }
  1643. X    fprintf(logfp, "%15.15s %s %s[%d]/%s ",
  1644. X        last_ctime+4, hostname,
  1645. X#if defined(DEBUG) && defined(PARANOID)
  1646. X        gargv[0],
  1647. X#else
  1648. X        progname,
  1649. X#endif
  1650. X        mypid,
  1651. X        sev);
  1652. X}
  1653. X
  1654. X#ifdef DEBUG
  1655. X/*VARARGS1*/
  1656. Xvoid dplog(fmt, j,s,_,p,e,n,d,r,y)
  1657. Xchar *fmt;
  1658. Xchar *j, *s, *_, *p, *e, *n, *d, *r, *y;
  1659. X{
  1660. X    plog(XLOG_DEBUG, fmt, j,s,_,p,e,n,d,r,y);
  1661. X}
  1662. X
  1663. X#endif
  1664. X/*VARARGS1*/
  1665. Xvoid plog(lvl, fmt, j,s,_,p,e,n,d,r,y)
  1666. Xint lvl;
  1667. Xchar *fmt;
  1668. Xchar *j, *s, *_, *p, *e, *n, *d, *r, *y;
  1669. X{
  1670. X    char msg[1024];
  1671. X    char efmt[1024];
  1672. X    char *ptr = msg;
  1673. X
  1674. X    if (!(xlog_level & lvl))
  1675. X        return;
  1676. X
  1677. X#ifdef DEBUG_MEM
  1678. X    checkup_mem();
  1679. X#endif
  1680. X
  1681. X    expand_error(fmt, efmt);
  1682. X    sprintf(ptr, efmt, j,s,_,p,e,n,d,r,y);
  1683. X    ptr += strlen(ptr);
  1684. X    if (ptr[-1] == '\n')
  1685. X        *--ptr  = '\0';
  1686. X#ifdef HAS_SYSLOG
  1687. X    if (syslogging) {
  1688. X        switch(lvl) {    /* from mike <mcooper@usc.edu> */
  1689. X        case XLOG_FATAL:    lvl = LOG_CRIT; break;
  1690. X        case XLOG_ERROR:     lvl = LOG_ERR; break;
  1691. X        case XLOG_USER:        lvl = LOG_WARNING; break;
  1692. X        case XLOG_WARNING:    lvl = LOG_WARNING; break;
  1693. X        case XLOG_INFO:        lvl = LOG_INFO; break;
  1694. X        case XLOG_DEBUG:    lvl = LOG_DEBUG; break;
  1695. X        case XLOG_MAP:        lvl = LOG_DEBUG; break;
  1696. X        case XLOG_STATS:    lvl = LOG_INFO; break;
  1697. X        default:        lvl = LOG_ERR; break;
  1698. X        }
  1699. X        syslog(lvl, "%s", msg);
  1700. X        return;
  1701. X    }
  1702. X#endif
  1703. X
  1704. X    *ptr++ = '\n';
  1705. X    *ptr = '\0';
  1706. X
  1707. X    /*
  1708. X     * Mimic syslog header
  1709. X     */
  1710. X    show_time_host_and_name(lvl);
  1711. X    fwrite(msg, ptr - msg, 1, logfp);
  1712. X    fflush(logfp);
  1713. X}
  1714. X
  1715. Xint bind_resv_port P((int so, u_short *pp));
  1716. Xint bind_resv_port(so, pp)
  1717. Xint so;
  1718. Xu_short *pp;
  1719. X{
  1720. X    struct sockaddr_in sin;
  1721. X    int rc;
  1722. X    unsigned short port;
  1723. X
  1724. X    bzero((voidp) &sin, sizeof(sin));
  1725. X    sin.sin_family = AF_INET;
  1726. X
  1727. X    port = IPPORT_RESERVED;
  1728. X
  1729. X    do {
  1730. X        --port;
  1731. X        sin.sin_port = htons(port);
  1732. X        rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
  1733. X    } while (rc < 0 && port > IPPORT_RESERVED/2);
  1734. X
  1735. X    if (pp && rc == 0)
  1736. X        *pp = port;
  1737. X    return rc;
  1738. X}
  1739. X
  1740. Xvoid forcibly_timeout_mp P((am_node *mp));
  1741. Xvoid forcibly_timeout_mp(mp)
  1742. Xam_node *mp;
  1743. X{
  1744. X    mntfs *mf = mp->am_mnt;
  1745. X    /*
  1746. X     * Arrange to timeout this node
  1747. X     */
  1748. X    if (mf && ((mp->am_flags & AMF_ROOT) ||
  1749. X        (mf->mf_flags & (MFF_MOUNTING|MFF_UNMOUNTING)))) {
  1750. X        if (!(mf->mf_flags & MFF_UNMOUNTING))
  1751. X            plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
  1752. X    } else {
  1753. X        plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
  1754. X        mp->am_flags &= ~AMF_NOTIMEOUT;
  1755. X        mp->am_ttl = clocktime();
  1756. X        reschedule_timeout_mp();
  1757. X    }
  1758. X}
  1759. X
  1760. Xvoid am_mounted P((am_node *mp));
  1761. Xvoid am_mounted(mp)
  1762. Xam_node *mp;
  1763. X{
  1764. X    mntfs *mf = mp->am_mnt;
  1765. X    int quoted;
  1766. X    mf->mf_flags |= MFF_MOUNTED;
  1767. X    mf->mf_error = 0;
  1768. X
  1769. X    /*
  1770. X     * Patch up path for direct mounts
  1771. X     */
  1772. X    if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &dfs_ops)
  1773. X        mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
  1774. X
  1775. X    /*
  1776. X     * Check whether this mount should be cached permanently
  1777. X     */
  1778. X    if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
  1779. X        mp->am_flags |= AMF_NOTIMEOUT;
  1780. X    } else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
  1781. X        mp->am_flags |= AMF_NOTIMEOUT;
  1782. X    } else {
  1783. X        struct mntent mnt;
  1784. X        mnt.mnt_opts = mf->mf_fo->opt_opts;
  1785. X        if (hasmntopt(&mnt, "nounmount"))
  1786. X            mp->am_flags |= AMF_NOTIMEOUT;
  1787. X        if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
  1788. X            mp->am_timeo = am_timeo;
  1789. X/*        if ((mf->mf_server->fs_pinger = hasmntval(&mnt, "ping")) == 0)
  1790. X            mf->mf_server->fs_pinger = AM_PINGER;
  1791. X*/
  1792. X    }
  1793. X
  1794. X    /*
  1795. X     * Do mounted callback
  1796. X     */
  1797. X    if (mf->mf_ops->mounted)
  1798. X        (*mf->mf_ops->mounted)(mf);
  1799. X
  1800. X    /*
  1801. X     * If this node is a symlink then
  1802. X     * compute the length of the returned string.
  1803. X     */
  1804. X    if (mf->mf_fattr.type == NFLNK)
  1805. X        mf->mf_fattr.size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
  1806. X
  1807. X    /*
  1808. X     * Record mount time
  1809. X     */
  1810. X    mp->am_stats.s_mtime = clocktime();
  1811. X    new_ttl(mp);
  1812. X
  1813. X    /*
  1814. X     * Log message
  1815. X     */
  1816. X    quoted = strchr(mf->mf_info, ' ') != 0;
  1817. X    plog(XLOG_INFO, "%s%s%s mounted fstype %s on %s",
  1818. X        quoted ? "\"" : "",
  1819. X        mf->mf_info,
  1820. X        quoted ? "\"" : "",
  1821. X        mf->mf_ops->fs_type, mf->mf_mount);
  1822. X
  1823. X    /*
  1824. X     * Update stats
  1825. X     */
  1826. X    amd_stats.d_mok++;
  1827. X}
  1828. X
  1829. Xint mount_node P((am_node *mp));
  1830. Xint mount_node(mp)
  1831. Xam_node *mp;
  1832. X{
  1833. X    mntfs *mf = mp->am_mnt;
  1834. X    int error;
  1835. X
  1836. X    mf->mf_flags |= MFF_MOUNTING;
  1837. X    error = (*mf->mf_ops->mount_fs)(mp);
  1838. X    mf = mp->am_mnt;
  1839. X    mf->mf_flags &= ~MFF_MOUNTING;
  1840. X    if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
  1841. X        /* ...but see ifs_mount */
  1842. X        am_mounted(mp);
  1843. X    }
  1844. X
  1845. X    return error;
  1846. X}
  1847. X
  1848. Xvoid am_unmounted P((am_node *mp));
  1849. Xvoid am_unmounted(mp)
  1850. Xam_node *mp;
  1851. X{
  1852. X    mntfs *mf = mp->am_mnt;
  1853. X
  1854. X    if (!foreground) /* firewall - should never happen */
  1855. X        return;
  1856. X
  1857. X#ifdef DEBUG
  1858. X    /*dlog("in am_unmounted(), foreground = %d", foreground);*/
  1859. X#endif
  1860. X
  1861. X    /*
  1862. X     * Do unmounted callback
  1863. X     */
  1864. X    if (mf->mf_ops->umounted)
  1865. X        (*mf->mf_ops->umounted)(mp);
  1866. X
  1867. X    free_map(mp);
  1868. X}
  1869. X
  1870. X
  1871. X/*
  1872. X * Fork the automounter
  1873. X *
  1874. X * TODO: Need a better strategy for handling errors
  1875. X */
  1876. Xstatic int dofork(P_void);
  1877. XINLINE
  1878. Xstatic int dofork()
  1879. X{
  1880. X    int pid;
  1881. Xtop:
  1882. X    pid = fork();
  1883. X
  1884. X    if (pid < 0) {
  1885. X        sleep(1);
  1886. X        goto top;
  1887. X    }
  1888. X
  1889. X    if (pid == 0) {
  1890. X        mypid = getpid();
  1891. X        foreground = 0;
  1892. X    }
  1893. X
  1894. X    return pid;
  1895. X}
  1896. X
  1897. Xint background(P_void);
  1898. Xint background()
  1899. X{
  1900. X    int pid = dofork();
  1901. X    if (pid == 0) {
  1902. X#ifdef DEBUG
  1903. X        dlog("backgrounded");
  1904. X#endif
  1905. X        foreground = 0;
  1906. X    }
  1907. X
  1908. X    return pid;
  1909. X}
  1910. X
  1911. Xint mkdirs P((char *path, int mode));
  1912. Xint mkdirs(path, mode)
  1913. Xchar *path;
  1914. Xint mode;
  1915. X{
  1916. X    /*
  1917. X     * take a copy in case path is in readonly store
  1918. X     */
  1919. X    char *p2 = strdup(path);
  1920. X    char *sp = p2;
  1921. X    struct stat stb;
  1922. X    int error_so_far = 0;
  1923. X
  1924. X    /*
  1925. X     * Skip through the string make the directories.
  1926. X     * Mostly ignore errors - the result is tested at the end.
  1927. X     *
  1928. X     * This assumes we are root so that we can do mkdir in a
  1929. X     * mode 555 directory...
  1930. X     */
  1931. X    while (sp = strchr(sp+1, '/')) {
  1932. X        *sp = '\0';
  1933. X        if (mkdir(p2, mode) < 0) {
  1934. X            error_so_far = errno;
  1935. X        } else {
  1936. X#ifdef DEBUG
  1937. X            dlog("mkdir(%s)", p2);
  1938. X#endif
  1939. X        }
  1940. X        *sp = '/';
  1941. X    }
  1942. X
  1943. X    if (mkdir(p2, mode) < 0) {
  1944. X        error_so_far = errno;
  1945. X    } else {
  1946. X#ifdef DEBUG
  1947. X        dlog("mkdir(%s)", p2);
  1948. X#endif
  1949. X    }
  1950. X
  1951. X    /*
  1952. X     * Do a sync - if we do rmdirs() immediately
  1953. X     * and then the system crashes it leaves
  1954. X     * the filesystem in a state that fsck -p
  1955. X     * can't fix.  (Observed more than once on
  1956. X     * SunOS 4 ...)
  1957. X     *
  1958. X     * This is an attempted workaround - XXX.
  1959. X     */
  1960. X    sync();
  1961. X
  1962. X    free(p2);
  1963. X
  1964. X    return stat(path, &stb) == 0 &&
  1965. X        (stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
  1966. X}
  1967. X
  1968. Xvoid rmdirs P((char *dir));
  1969. Xvoid rmdirs(dir)
  1970. Xchar *dir;
  1971. X{
  1972. X    char *xdp = strdup(dir);
  1973. X    char *dp;
  1974. X
  1975. X    do {
  1976. X        struct stat stb;
  1977. X        /*
  1978. X         * Try to find out whether this was
  1979. X         * created by amd.  Do this by checking
  1980. X         * for owner write permission.
  1981. X         */
  1982. X        if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
  1983. X            if (rmdir(xdp) < 0) {
  1984. X                if (errno != ENOTEMPTY && errno != EBUSY && errno != EEXIST)
  1985. X                    plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
  1986. X                break;
  1987. X            } else {
  1988. X#ifdef DEBUG
  1989. X                dlog("rmdir(%s)", xdp);
  1990. X#endif
  1991. X            }
  1992. X        } else {
  1993. X            break;
  1994. X        }
  1995. X        dp = strrchr(xdp, '/');
  1996. X        if (dp)
  1997. X            *dp = '\0';
  1998. X    } while (dp && dp > xdp);
  1999. X    free(xdp);
  2000. X}
  2001. X
  2002. X/*
  2003. X * Because the internal clock is only used for
  2004. X * timing out mounts, it does not have to be
  2005. X * particularly accurate, so long as it does not run
  2006. X * ahead of the real time.  So, to reduce the system
  2007. X * call overhead, repeated calls to gettimeofday()
  2008. X * are replaced by calls to the macro clocktime().
  2009. X * If the global time (clock_valid) is zero then
  2010. X * update_clocktime() is called to obtain the real time.
  2011. X * Before any system calls that are likely to block for a
  2012. X * significant time, the clock_valid value is set
  2013. X * so that the clock is recomputed next time it is
  2014. X * needed.
  2015. X */
  2016. X
  2017. Xtime_t clock_valid = 0;
  2018. X#ifndef clocktime
  2019. Xtime_t clocktime(P_void)
  2020. X{
  2021. X    return time(&clock_valid);
  2022. X}
  2023. X#endif
  2024. X
  2025. Xvoidp xmalloc(len)
  2026. Xint len;
  2027. X{
  2028. X    voidp p;
  2029. X    int retries = 600;
  2030. X
  2031. X    do {
  2032. X        p = (voidp) malloc((unsigned) len);
  2033. X        if (p) {
  2034. X#if defined(DEBUG) && defined(DEBUG_MEM)
  2035. X            Debug(D_MEM) plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
  2036. X#endif
  2037. X            return p;
  2038. X        }
  2039. X        if (retries > 0) {
  2040. X            plog(XLOG_ERROR, "Retrying memory allocation");
  2041. X            sleep(1);
  2042. X        }
  2043. X    } while (--retries);
  2044. X
  2045. X    plog(XLOG_FATAL, "Out of memory");
  2046. X    going_down(1);
  2047. X
  2048. X    abort();
  2049. X
  2050. X    return 0;
  2051. X}
  2052. X
  2053. X#if defined(DEBUG) && defined(DEBUG_MEM)
  2054. Xxfree(f, l, p)
  2055. Xchar *f;
  2056. Xint l;
  2057. Xvoidp p;
  2058. X{
  2059. X    Debug(D_MEM) plog(XLOG_DEBUG, "Free in %s:%d: block %#x", f, l, p);
  2060. X#undef free
  2061. X    free(p);
  2062. X}
  2063. X#endif
  2064. END_OF_FILE
  2065. if test 15603 -ne `wc -c <'util.c'`; then
  2066.     echo shar: \"'util.c'\" unpacked with wrong size!
  2067. fi
  2068. # end of 'util.c'
  2069. fi
  2070. echo shar: End of archive 9 \(of 13\).
  2071. cp /dev/null ark9isdone
  2072. MISSING=""
  2073. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  2074.     if test ! -f ark${I}isdone ; then
  2075.     MISSING="${MISSING} ${I}"
  2076.     fi
  2077. done
  2078. if test "${MISSING}" = "" ; then
  2079.     echo You have unpacked all 13 archives.
  2080.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2081. else
  2082.     echo You still need to unpack the following archives:
  2083.     echo "        " ${MISSING}
  2084. fi
  2085. ##  End of shell archive.
  2086. exit 0
  2087. exit 0 # Just in case...
  2088.